import {getRequestConfig} from '../ajax/getRequestConfig';
import {final} from '../final';
import {getPromiseValue} from '../getPromiseValue';
import {truest} from '../truest';

const fetchXhr=(config)=>{
    return fetch(config.url,config);
};
export const genRequest=({
    log,
    showLog=false,
    showToast,
    loading,
    getXhr=fetchXhr,
    addData=(data)=>{
        return data;
    },
    addHeaders=(header)=>{
        return header;
    },
    addBody=(body)=>{
        return body;
    },
    responseHandler=res=>res,
    errorHandler=err=>Promise.reject(err)
}={})=>{
    const _showToast=showToast;
    const _request = (arg) => {
        const {
            showLoading = true, showToast = false,
            showSuccess = false, showError = true,
            ..._arg
        } = arg;
        showLog&&log('requesting', _arg);
        let loadingHandler=null;
        if (loading&&showLoading) {
            loadingHandler=loading.show();
        }
        const config = getRequestConfig(_arg);

        const xhr =getXhr(config)
            .then((res) => {
                loadingHandler&&loadingHandler.hide();
                showLog&&log('request success', res);
                if(showToast || showSuccess){
                    _showToast&&_showToast(res);
                }
                return res;
            })
            .catch((...args) => {
                loadingHandler&&loadingHandler.hide();
                const [err]=args;
                showLog&&log('request err', err);
                if(showToast || showError){
                    _showToast&&_showToast(err);
                }
                return Promise.reject(...args)
            });
        return xhr;
    };
    return ({headers={},data={},body,...arg}={})=> {
        const preTask = [];
        preTask.push(getPromiseValue(addData(data)));
        preTask.push(getPromiseValue(addHeaders(headers)));
        preTask.push(getPromiseValue(addBody(body)));

        return Promise.all(preTask)
            .then(([data = {},headers = {},body] = []) => {
                return _request(truest({
                    ...arg,
                    headers,
                    data,
                    body
                }));
            })
            .then(responseHandler)
            .catch(errorHandler)
    };
};

export const genRequestWithRetry=({
    checkRetry=res=>false,
    responseHandler=res=>res,
    ...arg
}={})=>{
    const _request=genRequest(arg);
    const request=(arg,isRetrying)=>{
        return _request(arg)
            .then((res)=>{
                if(isRetrying){
                    return res;
                }
                return getPromiseValue(checkRetry(res))
                    .then((flag)=>{
                        if(flag){
                            return request(arg,true);
                        }
                        return res;
                    });
            })
            .then(responseHandler);

    };
    return request;
};
export default genRequest;